package com.example.secondhandspringboot.controller;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.secondhandspringboot.constant.RedisConstant;
import com.example.secondhandspringboot.context.BaseContext;
import com.example.secondhandspringboot.domain.dto.LoginDTO;
import com.example.secondhandspringboot.domain.dto.RegisterDto;
import com.example.secondhandspringboot.domain.dto.ResetEmailDTO;
import com.example.secondhandspringboot.domain.dto.UserInfoDTO;
import com.example.secondhandspringboot.domain.entity.User;
import com.example.secondhandspringboot.domain.vo.UserVO;
import com.example.secondhandspringboot.results.Result;
import com.example.secondhandspringboot.service.IUserService;
import com.example.secondhandspringboot.utils.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.validation.constraints.Email;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 周在林
 * @since 2024-03-30
 */
@RestController
@CrossOrigin
@RequestMapping("/user")
@Slf4j
@RequiredArgsConstructor
public class UserController {

    private final IUserService userService;
    private final StringRedisTemplate stringRedisTemplate;
    private final MailUtil mailUtil;

    /**
     * 注册
     * @return
     */
    @PostMapping("register")
    public Result register(@RequestBody RegisterDto registerDto){
        log.info("用户注册:"+registerDto);
        String email = registerDto.getEmail();
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail,email));
        if (user!=null){
            return Result.error("该用户已存在");
        }
        //redis中获取验证码
        String code = stringRedisTemplate.opsForValue().get(RedisConstant.REGISTER_EMAIL_KEY + email);
        //判断验证码
        if (Strings.isBlank(code)||Strings.isEmpty(code)){
            return Result.error("请先获取验证码");
        }
        String userCode = registerDto.getCaptcha();
        //判断用户输入的验证码为空
        if (userCode==null|| userCode.isEmpty()){
            return Result.error("请输入验证码");
        }
        //判断用户输入的验证码是否正确
        if (!userCode.equals(code)){
            return Result.error("验证码错误");
        }
        // 注册通过，缓存中验证码
        stringRedisTemplate.delete(RedisConstant.REGISTER_EMAIL_KEY + email);
        userService.register(registerDto.getEmail(),registerDto.getPassword(),registerDto.getSchoolId());
        return Result.success();
    }

    /**
     * 发送验证码
     * @param email
     * @return
     */
    @GetMapping("/sendCode")
    public Result sendCode(@RequestParam String email,@RequestParam int methods){
        log.info("发送验证码:"+email+"，获取方式："+methods);
        if (!ValidUtil.isValidEmail(email)){
            return Result.error("无效邮箱");
        }
        String code = CodeUtil.getCode();
        List<String> toEmail = new ArrayList<>();
        toEmail.add(email);
        String redisKey = "";
        if (methods==0){
            //注册
            redisKey = RedisConstant.REGISTER_EMAIL_KEY+email;
        }else if (methods==1){
            //登录验证
            redisKey = RedisConstant.LOGIN_EMAIL_KEY+email;
        } else if (methods==3) {
            //重置密码
            redisKey = RedisConstant.RESET_PWD_EMAIL_KEY+email;
        } else if (methods == 4) {
            //修改邮箱
            redisKey = RedisConstant.RESET_EMAIL_KEY+email;
        }
        stringRedisTemplate.opsForValue().set(redisKey,code,RedisConstant.EMAIL_VALID_TIME_OUT, TimeUnit.SECONDS);
        mailUtil.sendMailMessage(toEmail,code,methods);
        return Result.success();
    }

    /**
     * 用户登录
     * @return
     */
    @PostMapping("/login")
    public Result<String> userPwdLogin(@RequestBody LoginDTO loginDTO){
        String email = loginDTO.getEmail();
        if (!ValidUtil.isValidEmail(email)){
            return Result.error("邮箱格式错误");
        }
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail,email));
        if (Objects.isNull(user)){
            return Result.error("该用户不存在");
        }

        if (loginDTO.getLoginMethods()==1){
            //邮箱登录
            String code = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_EMAIL_KEY+email);
            if (!Objects.equals(code,loginDTO.getCaptcha())){
                return Result.error("验证码错误");
            }
            stringRedisTemplate.delete(RedisConstant.LOGIN_EMAIL_KEY+email);
        }else if (loginDTO.getLoginMethods()==2){
            //密码登录
            if (!Md5Util.checkPassword(loginDTO.getPassword(),user.getPassword())){
                return Result.error("密码错误");
            }
        }
        Map<String,Object> claims = new HashMap<>();
        claims.put("userId",user.getId());
        claims.put("email",user.getEmail());
        String token = JwtUtil.genToken(claims);
        log.info("当前用户："+user.getId());
        return Result.success(token);
    }

    /**
     * 重置密码
     * @param loginDTO
     * @return
     */
    @PostMapping("/resetPwd")
    public Result resetPwd(@RequestBody LoginDTO loginDTO){
        log.info("重置密码:"+loginDTO);
        String email = loginDTO.getEmail();
        if (!ValidUtil.isValidEmail(email)){
            return Result.error("邮箱格式错误");
        }
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail,email));
        if (Objects.isNull(user)){
            return Result.error("该用户不存在");
        }
        String code = stringRedisTemplate.opsForValue().get(RedisConstant.RESET_PWD_EMAIL_KEY+email);
        if (code==null|| code.isEmpty()){
            return Result.error("请获取验证码");
        }
        if (!Objects.equals(loginDTO.getCaptcha(),code)){
            return Result.error("验证码错误");
        }
        stringRedisTemplate.delete(RedisConstant.RESET_PWD_EMAIL_KEY+email);
        user.setPassword(Md5Util.getMD5String(loginDTO.getPassword()));
        user.setUpdateTime(LocalDateTime.now());
        userService.updateById(user);
        return Result.success();
    }

    /**
     * 修改邮箱
     * @param resetEmailDTO
     * @return
     */
    @PutMapping("/resetEmail")
    @CacheEvict(cacheNames = "userInfoCache", key = "#resetEmailDTO.id")
    public Result resetEmail(@RequestBody ResetEmailDTO resetEmailDTO){
        log.info("修改用户邮箱");
        String newEmail = resetEmailDTO.getNewEmail();
        String oldEmail = resetEmailDTO.getEmail();
        if (!ValidUtil.isValidEmail(newEmail)){
            return Result.error("邮箱格式错误");
        }
        if (Objects.equals(oldEmail,newEmail)){
            return Result.error("新邮箱与旧邮箱重复");
        }
        String captcha = resetEmailDTO.getCaptcha();
        String redisCaptcha = stringRedisTemplate.opsForValue().get(RedisConstant.RESET_EMAIL_KEY + oldEmail);
        if (redisCaptcha == null)
        {
            return Result.error("请先获取验证码");
        }
        if (!Objects.equals(captcha,redisCaptcha)){
            return Result.error("验证码错误");
        }
        //新邮箱是否存在
        if (userService.getOne(new LambdaQueryWrapper<>(User.class).eq(User::getEmail, newEmail)) != null){
            return Result.error("该邮箱已存在");
        }

        stringRedisTemplate.delete(RedisConstant.RESET_EMAIL_KEY+oldEmail);

        User user = userService.getById(resetEmailDTO.getId());
        user.setEmail(newEmail);
        user.setUpdateTime(LocalDateTime.now());
        userService.updateById(user);
        return Result.success();
    }

    /**
     * 获取用户信息
     * @return
     */
    @GetMapping("/userInfo")
    @Cacheable(cacheNames = "userInfoCache",key = "#context.currentId")
    public Result<UserVO> userInfo(BaseContext context){
        log.info("获取用户信息");
        Long userId = BaseContext.getCurrentId();
        UserVO userVO = userService.getUserVOByUserId(userId);
        return Result.success(userVO);
    }

    /**
     * 完善用户信息
     * @return
     */
    @PutMapping("/perfectUserInfo")
    @CacheEvict(cacheNames = "userInfoCache", key = "#userInfoDTO.id")       
    public Result perfectUserInfo(@RequestBody UserInfoDTO userInfoDTO){
        User user = new User();
        //获取用户id
        user.setId(userInfoDTO.getId());
        user.setUserPic(userInfoDTO.getUserPic());
        user.setUsername(userInfoDTO.getUsername());
        user.setPhone(userInfoDTO.getPhone());
        user.setDepartment(userInfoDTO.getDepartment());
        user.setClassName(userInfoDTO.getClassName());
        user.setQqNumber(userInfoDTO.getQqNumber());
        user.setUpdateTime(LocalDateTime.now());

        userService.updateById(user);

        return Result.success();
    }

}
